﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MARZ_Script.analysis;
using MARZ_Script.lexer;
using MARZ_Script.node;
using MARZ_Script.parser;

namespace SableCC15.CodeGeneration
{
    class ControlStructCodeGen : DepthFirstAdapter
    {
        public override void CaseAWhile(AWhile node)
        {
            Utility.Emit(node.GetTWhile().Text.ToLower() + "(");
            if (node.GetExpressionOpt() is ASingleExpressionOpt) //Test if theres a predicate otherwise always true
            {
                node.GetExpressionOpt().Apply(new CodeGeneration.ExpressionCodeGen());
            }
            else
                Utility.Emit("true");
            Utility.Emit(")" + "{");
            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
            Utility.Emit("}");

        }

        #region if
        public override void CaseAIf(AIf node)
        {
            Utility.Emit("if" + "(");
            node.GetIfBody().Apply(this);
        }

        public override void CaseAIfBody(AIfBody node)
        {
            if (node.GetExpressionOpt() is ASingleExpressionOpt) //Test if theres a predicate otherwise always true
            {
                node.GetExpressionOpt().Apply(new CodeGeneration.ExpressionCodeGen(true));
            }
            else
                Utility.Emit("true");
            Utility.Emit(")" + "{");
            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
   
            node.GetElse().Apply(this);

        }

        public override void CaseAElseIfElse(AElseIfElse node)
        {
            Utility.Emit("}");
            Utility.Emit(node.GetTElseIf().Text.ToLower() + "(");
            node.GetIfBody().Apply(this);
        }

        public override void CaseAElseElse(AElseElse node)
        {
            Utility.Emit(node.GetTElse().Text.ToLower() + "{");
            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
        }
        public override void CaseAEndElse(AEndElse node)
        {
            Utility.Emit("}");
        }

        #endregion


        #region for
        public override void CaseAFor(AFor node)
        {
            Utility.Emit(node.GetTFor().Text.ToLower() + "(");
            node.GetCounterId().Apply(this);
            Utility.Emit(";" + node.GetCounterId().NodeType);
            node.GetForTo().Apply(this);
            Utility.Emit(";" + node.GetCounterId().NodeType);
            if (node.GetOffset() is AEmptyOffset)
            {
                if (node.GetForTo().NodeType == "upto")
                    Utility.Emit("++");
                else
                    Utility.Emit("--");

            }
            else
            {
                node.GetOffset().Apply(this);
            }
            Utility.Emit("){");
            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
            Utility.Emit("}");
        }

        public override void CaseADeclIdCounterId(ADeclIdCounterId node)
        {
            Utility.Emit("int " + node.GetId().Text + "=" + node.GetIntliteral().Text);
            node.NodeType = node.GetId().Text;
        }
        public override void CaseACounterId(ACounterId node)
        {
            node.NodeType = node.GetId().Text;
        }

        public override void CaseADIdForTo(ADIdForTo node)
        {
            Utility.Emit("<=" + node.GetId().Text);
            node.NodeType = "downto";
        }
        public override void CaseADLitForTo(ADLitForTo node)
        {
            Utility.Emit("<=" + node.GetIntliteral().Text);
            node.NodeType = "downto";
        }

        public override void CaseAUIdForTo(AUIdForTo node)
        {
            Utility.Emit(">=" + node.GetId().Text);
            node.NodeType = "upto";
        }
        public override void CaseAULitForTo(AULitForTo node)
        {
            Utility.Emit(">=" + node.GetIntliteral().Text);
            node.NodeType = "upto";
        }

        public override void CaseAExprOffset(AExprOffset node)
        {
            Utility.Emit("+=");
            node.GetConditionalExp().Apply(new CodeGeneration.ExpressionCodeGen());
        }

        #endregion

        #region switch
        public override void CaseASwitch(ASwitch node)
        {
            Utility.Emit(node.GetTSwitch().Text.ToLower() + "(");
            node.GetScalar().Apply(new CodeGeneration.ExpressionCodeGen());
            Utility.Emit(")" + "{");
            node.GetCases().Apply(this);
            Utility.Emit("}");
        }

        public override void CaseACase(ACase node)
        {
            Utility.Emit(node.GetTCase().Text.ToLower() + " ");
            node.GetScalar().Apply(new CodeGeneration.ExpressionCodeGen());
            Utility.Emit(node.GetOpDo().Text + " ");
            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
            Utility.Emit("break;");
        }
        public override void CaseADefault(ADefault node)
        {
            Utility.Emit(node.GetTDefault().Text.ToLower());
            Utility.Emit(node.GetOpDo().Text + " ");

            node.GetBodyList().Apply(new CodeGeneration.CodeGenerator());
            Utility.Emit("break;");
        }
        #endregion
    }
}
